/*
 * activity.cpp
 *
 *  Created on: 10 Şub 2012
 *      Author: root
 */

#include "activity.h"





namespace androidplus {

activity::activity() {

		status.state = ACTIVITY_STOPED; //set application status state to APP_STOPED
		current_config = NULL;
		native.window=NULL;
		native.activity=NULL;
		input.queue=NULL;
	    saved_state.data=NULL;
	    saved_state.len=0;
	    saved_state.saved=0;

}

activity::~activity() {
	    LOGI("Activity deconstructer called");
		if(saved_state.data!=NULL)
		  delete saved_state.data;
	      pthread_mutex_destroy(&threading.mutex);
	      pthread_cond_broadcast(&threading.condition);
	      current_config=NULL;
	      saved_state.data=NULL;
	      saved_state.len=0;
	      saved_state.saved=0;



}

int activity::state()const
{
	return status.state;
}

and_config * activity::cur_conf() {
	return current_config;
}

ANativeWindow * activity::cur_native_window()
{
	return native.window;
}

void activity::init(ANativeActivity* activity, void* savedState,
		size_t savedStateSize) {
	LOGI("Activity Init");

	activity->instance=this;
	native.activity = activity;

	if(savedState!=NULL){
		LOGI("Saving State At Init");
	saved_state.data =new char[savedStateSize];
	memcpy(saved_state.data,savedState,savedStateSize);
	saved_state.len = savedStateSize;
	saved_state.saved=1;
	}

	threading_init();
}

void * threading_entry(void *arg) {

	LOGI("Activity Threading Entry");
	activity *act = (activity *) arg;
	AConfiguration *aconf = AConfiguration_new();
	act->init_conf(aconf);

	ALooper* looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);


	ALooper_addFd(looper, act->current_messaging->fd(),
			androidplus::messaging::message::LOOPER_ID_MSG, ALOOPER_EVENT_INPUT, NULL,NULL);

	act->poll.looper = looper;

	act->threading_lock_mutex();
	act->status.state = activity::ACTIVITY_RUNNING;

	act->threading_condition_broadcast();

	act->threading_unlock_mutex();

	android_main();


	return NULL;

}

void activity::threading_init() {
	pthread_mutex_init(&threading.mutex, NULL);
	pthread_cond_init(&threading.condition, NULL);

	pthread_attr_t attr;
	pthread_attr_init(&attr);
	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
	pthread_create(&threading.thread, &attr, threading_entry, this);
	threading_lock_mutex();
	while (status.state != activity::ACTIVITY_RUNNING)
		threading_condition_wait();
	threading_unlock_mutex();

}


void activity::on_start() {
	threading_lock_mutex();
	current_messaging->write_message(new androidplus::messaging::activity::message_activity_start);
	while (status.state != activity::ACTIVITY_RUNNING)
		threading_condition_wait();

	threading_unlock_mutex();

}
void activity::on_resume() {
	threading_lock_mutex();
	current_messaging->write_message(new messaging::activity::message_activity_resume());
	while (status.state !=activity::ACTIVITY_RUNNING)
		threading_condition_wait();
	threading_unlock_mutex();

}
void* activity::on_save_instance_state(size_t* outSize) {
	threading_lock_mutex();
	saved_state.saved=0;
	current_messaging->write_message(new messaging::activity::message_activity_save_state);
	while(saved_state.saved==0)
		threading_condition_wait();
	*outSize=this->saved_state.len;
	void *ret_data= this->saved_state.data;
	this->saved_state.data=NULL;
	this->saved_state.len=0;
	this->saved_state.saved=0;
	threading_unlock_mutex();
	return ret_data;



}
void activity::on_pause() {

	threading_lock_mutex();
	current_messaging->write_message(new messaging::activity::message_activity_pause);
	while (status.state != ACTIVITY_PAUSED)
		threading_condition_wait();
	threading_unlock_mutex();
}
void activity::on_stop() {
	threading_lock_mutex();
	current_messaging->write_message(new messaging::activity::message_activity_stop);
	while (status.state != ACTIVITY_STOPED)
		threading_condition_wait();
	threading_unlock_mutex();

}
void activity::on_destroy() {
	threading_lock_mutex();
	current_messaging->write_message(new messaging::activity::message_activity_destroy);
	while(status.state!=ACTIVITY_DESTROYED)
		threading_condition_wait();


	//ALooper_removeFd(poll.looper,current_messaging->fd());
	delete current_config;
	threading_unlock_mutex();



}
void activity::on_window_focus_changed(int hasFocus) {
	//todo implement this
	/*if(hasFocus)
	 current_messaging->write_message(new messaging::activity::message_activity_gained_focus);
	 else
	 current_messaging->write_message(new messaging::activity::message_activity_lost_focus);*/

}
void activity::on_native_window_created(ANativeWindow* window) {

	threading_lock_mutex();
	current_messaging->write_message(
			new messaging::activity::message_activity_init_window(window));
	while (native.window == NULL)
		threading_condition_wait();
	threading_unlock_mutex();
	on_native_window_redraw_needed(NULL);

}
void activity::on_native_window_resized(ANativeWindow* window) {
	//todo implement this
	//current_messaging->write_message(new messaging::activity::message_activity_window_resized);

}
void activity::on_native_window_redraw_needed(ANativeWindow* window) {
	threading_lock_mutex();
	rendering.is_rendered_finished=t_false;
	current_messaging->write_message(new messaging::activity::message_activity_window_redraw_needed);
	while(rendering.is_rendered_finished==t_false)
		threading_condition_wait();
	threading_unlock_mutex();

}
void activity::on_native_window_destroyed(ANativeWindow* window) {
	threading_lock_mutex();
	current_messaging->write_message(
			new messaging::activity::message_activity_term_window);
	while (native.window != NULL)
		threading_condition_wait();
	threading_unlock_mutex();
}
void activity::on_input_queue_created(AInputQueue* queue) {
	threading_lock_mutex();
	current_messaging->write_message(
			new messaging::activity::message_activity_input_changed(queue));
	while (input.queue == NULL)
		threading_condition_wait();
	threading_unlock_mutex();

}
void activity::on_input_queue_destroyed(AInputQueue* queue) {

	threading_lock_mutex();
	current_messaging->write_message(
			new messaging::activity::message_activity_input_changed(NULL));
	while (input.queue != NULL)
		threading_condition_wait();
	threading_unlock_mutex();
}

void activity::on_content_rect_changed(const ARect* rect) {
	//todo implement this
	//current_messaging->write_message(new messaging::activity::message_activity_content_rect_changed);

}
void activity::on_configuration_changed() {
	threading_lock_mutex();
	current_messaging->write_message(
			new messaging::activity::message_activity_config_changed);

}
void activity::on_low_memory() {
	//todo implement this
	//current_messaging->write_message(new messaging::activity::message_activity_low_memory);
}

void activity::threading_lock_mutex() {
	pthread_mutex_lock(&threading.mutex);

}
void activity::threading_unlock_mutex() {
	pthread_mutex_unlock(&threading.mutex);
}
void activity::threading_condition_wait() {
	pthread_cond_wait(&threading.condition, &threading.mutex);

}
void activity::threading_condition_broadcast() {
	pthread_cond_broadcast(&threading.condition);

}

void activity::init_conf(AConfiguration *conf) {
	//TODO not a good desing if this->current_config is NULL then FATAL
	//also current config must not delete

	if (conf == NULL){
		conf = this->current_config->aconf;
	}
	if (this->current_config != NULL){
		delete current_config;
	}
	AConfiguration_fromAssetManager(conf, this->native.activity->assetManager);
	this->current_config = new and_config(conf);
}


void activity::process_msg() {

    threading_lock_mutex();
    LOGI("Processing Msg");
	messaging::message *msg = NULL;
	int res = current_messaging->read_message(&msg);
	if (res < 0) {
		LOGI("Message Read Error");
		threading_unlock_mutex();
	} else {
		//LOGI("Readed Msg Number:%d",msg->msg_number());
		threading_unlock_mutex();
		msg->execute();
		delete msg;
		//LOGI("Message Executed");

	}


}

void  activity::process_input() {


	threading_lock_mutex();
	LOGI("Processing Input");
	AInputEvent* event = NULL;
	if (AInputQueue_getEvent(input.queue, &event) >= 0) {
		int32_t event_type=AInputEvent_getType(event);
		LOGI("New input event: type=%d\n",event_type);
		input::input_handler().handle(event);

		if (AInputQueue_preDispatchEvent(input.queue, event)) {
			threading_unlock_mutex();
			return;

		}
		int32_t handled = 0;
		//if (app->onInputEvent != NULL) handled = app->onInputEvent(app, event);
		AInputQueue_finishEvent(input.queue, event, handled);
	} else {
		LOGI("Failure reading next input event: %s\n", strerror(errno));
	}
	threading_unlock_mutex();
}




} /* namespace androidplus */




